<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Admin\Traits\AdminTrait;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\BaseRequest;
use App\Models\Admin\AdminRegion;
use App\Models\Admin\AdminSetting;
use App\Models\Admin\Company;
use App\Models\Admin\GoodsCategory;
use App\Models\Admin\GoodsDatum;
use App\Models\Admin\GoodsStandard;
use App\Models\Admin\GoodsStandardSpu;
use App\Models\Admin\Order;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

class DataController extends Controller
{
    use AdminTrait;

    /**
     * @var
     */
    protected $virtual_data;

    /**
     * @param Request $request
     * @param string $prefix
     * @return \Illuminate\Http\JsonResponse
     */
    public function index(Request $request, $prefix = '')
    {
        if (strlen($prefix) != 12) {
            return $this->error(['-1', '参数错误']);
        }
        $key = 'share_' . substr(md5(substr(sha1($prefix), 0, 12) . $this->return_appsecret() . $prefix), 6, 12);
        $val = Redis::get($key);
        if (empty($val)) {
            abort(403, '网页已过期,请重新申请链接');
        }
        $info = DB::table('statistics_virtual_data')->where(['type'=>12])->first();
        $data = [];
        if(!empty($info)) {
            $data = json_decode($info->virtual_data,true);
        }
        return $this->success(['data'=>$data]);
    }

    /**
     * System total transaction amount
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getTotal(BaseRequest $request)
    {
        $real = $request->query('real') ?? 1;
        $info = $this->getVirtualData(1,$real);
        $is_virtual = 0;
        if (empty($info)) {
            $virtual_data = $this->__getTotal();
        } else {
            $is_virtual = 1;
            $virtual_data = json_decode($info->virtual_data, true);
        }
        return $this->success(['data' => $virtual_data, 'is_virtual' => $is_virtual]);
    }

    /**
     * @return array
     */
    protected function __getTotal()
    {
        $same_day_money = Order::selectRaw("SUM(send_money) as send_money")->whereIn('order_status', [2, 3])->where('send_time', Carbon::today()->timestamp)->first()->send_money;
        $same_month_money = DB::table('statistics_customer_month')->selectRaw("SUM(amount) as send_money")->where('timestamps', Carbon::now()->startOfMonth()->timestamp)->first()->send_money + $same_day_money;
        $same_year_money = DB::table('statistics_customer_year')->selectRaw("SUM(amount) as send_money")->where('timestamps','<=', Carbon::now()->startOfYear()->timestamp)->first()->send_money + $same_day_money;
        $virtual_data = [
            'day' => round($same_day_money,2),
            'month' => round($same_month_money,2),
            'year' => round($same_year_money,2)
        ];
        return $virtual_data;
    }

    /**
     * Transaction overview in recent year
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getLastYearTradeMoney(BaseRequest $request)
    {
        $real = $request->query('real') ?? 1;
        $info = $this->getVirtualData(3,$real);
        $is_virtual = 0;
        if (empty($info)) {
            $virtual_data = $this->__getLastYearTradeMoney();
        } else {
            $is_virtual = 1;
            $virtual_data = json_decode($info->virtual_data, true);
        }
        return $this->success(['data' => $virtual_data, 'is_virtual' => $is_virtual]);
    }

    /**
     * @return array
     */
    protected function __getLastYearTradeMoney()
    {
        $start_time = Carbon::parse('-1 year')->startOfMonth()->timestamp;
        $end_time = Carbon::now()->startOfMonth()->timestamp - 1;
        $month_money = DB::table('statistics_customer_month')->selectRaw("SUM(amount) as send_money,dates")->whereBetween('timestamps', [$start_time, $end_time])->groupBy('dates')->get();
        if ($month_money->isNotEmpty()) {
            return $month_money->toArray();
        } else {
            return [];
        }
    }

    /**
     * Distribution of cooperative customers in various regions
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getGuestRegionSpread(BaseRequest $request)
    {
        $real = $request->query('real') ?? 1;
        $info = $this->getVirtualData(4,$real);
        $is_virtual = 0;
        if (empty($info)) {
            $virtual_data = $this->__getGuestRegionSpread();
        } else {
            $is_virtual = 1;
            $virtual_data = json_decode($info->virtual_data, true);
        }
        return $this->success(['data' => $virtual_data,'is_virtual'=>$is_virtual]);
    }

    protected function __getGuestRegionSpread()
    {
        $count = $this->__getGuestCount();
        $province = Company::selectRaw('COUNT(*) as count,CONCAT(LEFT(base_address,2),"0000") as province')->groupBy('province')->get();
        if ($province->isNotEmpty()) {
            $code = $province->pluck('province');
            $region = AdminRegion::select('id','name')->whereIn('id',$code)->get()->keyBy('id');
            $province = $province->toArray();
            foreach ($province as $k => $v) {
                $province[$k]['rate'] = round($v['count']/$count*100,2);
                $province[$k]['province_name'] = $region[$v['province']]->name;
                unset($province[$k]['province']);
                unset($province[$k]['count']);
            }
            return $province;
        } else {
            return [];
        }
    }

    /**
     * Proportion of cooperative customer types
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getGuestTypeProportion(BaseRequest $request)
    {
        $real = $request->query('real') ?? 1;
        $info = $this->getVirtualData(5,$real);
        $is_virtual = 0;
        if (empty($info)) {
            $virtual_data = $this->__getGuestTypeProportion();
        } else {
            $is_virtual = 1;
            $virtual_data = json_decode($info->virtual_data,true);
        }
        return $this->success(['data'=>$virtual_data,'is_virtual'=>$is_virtual]);
    }

    protected function __getGuestTypeProportion()
    {
        $model = [
            1 => '批发',
            2 => '城配',
            3 => '软件'
        ];
        $count = $this->__getGuestCount();
        $type = Company::selectRaw("COUNT(*) as count,model")->groupBy('model')->get();
        if ($type->isNotEmpty()) {
            $type = $type->toArray();
            foreach ($type as $k => $v) {
                $type[$k]['name'] = $model[$v['model']];
                $type[$k]['rate'] = round(($v['count']/$count)*100,2);
                unset($type[$k]['count']);
                unset($type[$k]['model']);
            }
            return $type;
        } else {
            return [];
        }
    }

    protected function __getGuestCount()
    {
        return Company::select('id')->count();
    }

    /**
     * Top 10 trading volume of cooperative customers
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getGuestTradingVolume(BaseRequest $request)
    {
        $real = $request->query('real') ?? 1;
        $info = $this->getVirtualData(6,$real);
        $is_virtual = 0;
        if (empty($info)) {
            $virtual_data = $this->__getGuest('amount');
        } else {
            $is_virtual = 1;
            $virtual_data = json_decode($info->virtual_data,true);
        }
        return $this->success(['data'=>$virtual_data,'is_virtual'=>$is_virtual]);
    }

    /**
     * Top 10 orders of cooperative customers
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getGuestOrders(BaseRequest $request)
    {
        $real = $request->query('real') ?? 1;
        $info = $this->getVirtualData(7,$real);
        $is_virtual = 0;
        if (empty($info)) {
            $virtual_data = $this->__getGuest('order_volume');
        } else {
            $is_virtual = 1;
            $virtual_data = json_decode($info->virtual_data,true);
        }
        return $this->success(['data'=>$virtual_data,'is_virtual'=>$is_virtual]);
    }

    /**
     * Top 10 user number of cooperative customers
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getGuestUserNumber(BaseRequest $request)
    {
        $real = $request->query('real') ?? 1;
        $info = $this->getVirtualData(8,$real);
        $is_virtual = 0;
        if (empty($info)) {
            $virtual_data = $this->__getGuest('user_number');
        } else {
            $is_virtual = 1;
            $virtual_data = json_decode($info->virtual_data,true);
        }
        return $this->success(['data'=>$virtual_data,'is_virtual'=>$is_virtual]);
    }

    /**
     * @param string $field
     * @return array
     */
    protected function __getGuest($field='amount')
    {
        $list = Company::select('company_name',$field)->orderBy($field,'desc')->limit(10)->get();
        if ($list->isNotEmpty()) {
            return $list->toArray();
        } else {
            return [];
        }
    }

    /**
     * Standard classification sales distribution
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getStandardCategorySalesSpread(BaseRequest $request)
    {
        $real = $request->query('real') ?? 1;
        $info = $this->getVirtualData(9,$real);
        $is_virtual = 0;
        if (empty($info)) {
            $virtual_data = $this->__getStandardCategorySalesSpread();
        } else {
            $is_virtual = 1;
            $virtual_data = json_decode($info->virtual_data,true);
        }
        return $this->success(['data'=>$virtual_data,'is_virtual'=>$is_virtual]);
    }

    /**
     * @return array
     */
    protected function __getStandardCategorySalesSpread()
    {
        $list = DB::table('statistics_goods')
            ->selectRaw('SUM(sales) as sales,(SELECT pid FROM '.config('database.connections.mysql.prefix').'goods_standard where id=goods_id) as pid')
            ->groupBy('pid')->get();
        if ($list->isNotEmpty()) {
            $pids = $list->pluck('pid');
            $categories = GoodsCategory::whereIn('id',$pids)->select('id','title')->get()->pluck('title','id');
            $data = [];
            foreach ($list as $k => $v) {
                if(!isset($categories[$v->pid])) continue;
                $data[] = [
                    'name' => $categories[$v->pid],
                    'sales' => $v->sales
                ];
            }
            return $data;
        } else {
            return [];
        }
    }

    /**
     * Top 10 standard library commodity sales
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getStandardGoodsSale(BaseRequest $request)
    {
        $real = $request->query('real') ?? 1;
        $info = $this->getVirtualData(10,$real);
        $is_virtual = 0;
        if (empty($info)) {
            $virtual_data = $this->__getStandardGoods('sales');
        } else {
            $is_virtual = 1;
            $virtual_data = json_decode($info->virtual_data,true);
        }
        return $this->success(['data'=>$virtual_data,'is_virtual'=>$is_virtual]);
    }

    /**
     *Top 10 standard library commodity transactions
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getStandardGoodsTrading(BaseRequest $request)
    {
        $real = $request->query('real') ?? 1;
        $info = $this->getVirtualData(11,$real);
        $is_virtual = 0;
        if (empty($info)) {
            $virtual_data = $this->__getStandardGoods('amount');
        } else {
            $is_virtual = 1;
            $virtual_data = json_decode($info->virtual_data,true);
        }
        return $this->success(['data'=>$virtual_data,'is_virtual'=>$is_virtual]);
    }

    /**
     * @param string $field
     * @return array
     */
    protected function __getStandardGoods($field='amount')
    {
        $list = DB::table('statistics_goods')->select('goods_id','goods_spu_id',$field)->orderBy($field,'desc')->limit(10)->get();
        if ($list->isNotEmpty()) {
            $goods_ids = $list->pluck('goods_id');
            $goods_spu_ids = $list->pluck('goods_spu_id');
            $goods = GoodsStandard::select('id','name')->whereIn('id',$goods_ids)->get()->keyBy('id');
            $goods_spu = GoodsStandardSpu::select('id','spu_name')->whereIn('id',$goods_spu_ids)->get()->keyBy('id');
            $datums = GoodsDatum::select('id','title')->where('company_id',0)->pluck('title','id');
            $data = [];
            foreach ($list as $k => $v) {
                if (!isset($goods[$v->goods_id]) || !isset($goods_spu[$v->goods_spu_id]) || !isset($datums[$goods_spu[$v->goods_spu_id]->spu_name])) continue;
                $data[] = [
                    'name' => $goods[$v->goods_id]->name.'【'.$datums[$goods_spu[$v->goods_spu_id]->spu_name].'】',
                    'amount' => $v->$field,
                ];
            }
            return $data;
        } else {
            return [];
        }
    }


    public function getCompanyLogLat(BaseRequest $request)
    {
        $real = $request->query('real') ?? 1;
        $info = $this->getVirtualData(2,$real);
        $is_virtual = 0;
        if (empty($info)) {
            $virtual_data = $this->__getCompanyLogLat();
        } else {
            $is_virtual = 1;
            $virtual_data = json_decode($info->virtual_data,true);
        }
        return $this->success(['data'=>$virtual_data,'is_virtual'=>$is_virtual]);
    }

    protected function __getCompanyLogLat()
    {
        $list = DB::table('company')->select('name','long_lati')->get();
        return $list;
    }

    /**
     * @param int $type
     * @param int $real
     * @return array|\Illuminate\Database\Eloquent\Model|\Illuminate\Database\Query\Builder|object|null
     */
    protected function getVirtualData($type=0,$real=0)
    {
        if ($real) return [];
        return DB::table('statistics_virtual_data')->where('type',$type)->where('status',1)->first();
    }

    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function saveData(BaseRequest $request)
    {
        $data = $request->get('data');
        $type = $request->get('type');
        $status = $request->get('status');

        if ($type > 17 || $type < 1) {
            $this->error(['-1','参数错误']);
        }
        $info = $this->getVirtualData($type);
        if (!$status && !empty($info)) {
            $info->status = 0;
            $info->save();
            return $this->success();
        }
        if (empty($info)) {
            DB::table('statistics_virtual_data')->insert([
                'type' => $type,
                'virtual_data' => $data,
                'status' => 1
            ]);
        } else {
            $info->status = 1;
          /*  $info->virtual_data = $data;
            $info->save();*/
            DB::table('statistics_virtual_data')->where(['type'=>$info->type])->update(['virtual_data'=>$data]);
        }
        return $this->success();
    }

    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function share(BaseRequest $request)
    {
        $hours = $request->get('hour');
        $rand_str = $this->str_rand();
        $key = 'share_'.substr(md5(substr(sha1($rand_str),0,12).$this->return_appsecret().$rand_str),6,12);
        $data = [
            'value' => $rand_str,
            'expire_time' => time()+$hours*3600
        ];
        Redis::set($key,json_encode($data));
        Redis::expire($key, $hours*3600);

        $share_url = $this->getHttpHost().'/I/'.$rand_str;

        $data = $request->get('data');
        $type = $request->get('type');
        $status = $request->get('status');

        if ($type > 12 || $type < 1) {
            $this->error(['-1','参数错误']);
        }
        $info = $this->getVirtualData($type);
        if (!$status && !empty($info)) {
            $info->status = 0;
            $info->save();
            return $this->success();
        }
        if (empty($info)) {
            DB::table('statistics_virtual_data')->insert([
                'type' => $type,
                'virtual_data' => $data,
                'status' => 1
            ]);
        } else {
            $info->status = 1;
            DB::table('statistics_virtual_data')->where(['type'=>$info->type])->update(['virtual_data'=>$data]);
        }


        return $this->success(['share_url'=>$share_url]);
    }

    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function getShareUrl(Request $request)
    {
        $keys = Redis::keys('share_*');
        $data = [];
        $host = $this->getHttpHost();
        foreach ($keys as $key) {
            $arr = Redis::get($key);
            $arr = json_decode($arr,true);
            $data[] = [
                'url' => $host.'/I/'.$arr['value'],
                'expire_time' => $arr['expire_time']
            ];
        }
        return $this->success($data);
    }

    public function delete(Request $request)
    {
        $prefix = $request->get('prefix');
        if (empty($prefix)) {
            redis_clear('share_');
        } else {
            $key = 'share_' . substr(md5(substr(sha1($prefix), 0, 12) . $this->return_appsecret() . $prefix), 6, 12);
            Redis::del($key);
        }
        return $this->success();
    }

    public function getSelect(Request $request)
    {
        $info = DB::table('statistics_virtual_data')->where('type',12)->first();
        $data = [];
        if(!empty($info)) {
            $data = json_decode($info->virtual_data,true);
        }
        return $this->success(['data'=>$data]);
    }

    public function saveSelect(Request $request)
    {
        return false;
        $data = $request->get('data');
        $info = DB::table('statistics_setting')->first();
        if (empty($info)) {
            DB::table('statistics_setting')->insert(['setting'=>$data]);
        } else {
            DB::table('statistics_setting')->update(['setting'=>$data]);
        }
        return $this->success();
    }

    public function getSort(Request $request)
    {
        $info = DB::table('statistics_virtual_data')->where('type',13)->first();
        $data = [];
        if(!empty($info)) {
            $data = json_decode($info->virtual_data,true);
        }
        return $this->success(['data'=>$data]);
    }
}
